SyncSim manual

Contents
1.0 How to create a new Part
1.1 The Making of an AND-gate
1.2 The graphical representation of a Part
1.3 The Making of a register
2.0 Making a design file
2.1 The Simulator tag
2.2 The Component tag


1.0 How to create a new Part
The first step when writing a new part for SoftSim is to identify if the part is combinatorial or synchronous. If the part is combinatorial it should inherit SoftPart, otherwise it should inherit SoftSyncPart. In SoftSim there is no difference between the two if you look at the functions supported, but the simulator treats the two classes different internally. The second step is to implement the required methods, which can be tricky if you don’t know what you’re doing.
 
1.1 The Making of an AND-gate
Since an AND-gate is combinatorial we create a class according to the naming convention and inherit SoftPart. We want the gate to be as general as possible and to be able to do the and operation on different bit widths is one way of increasing the flexibility of the part. Another way could be to have n-number of inputs to the gate, but this example will only go through the first of the two choices. The Part must have a constructor that doesn't take any argument because the design Loader can only create classes with an empty argument list.

import java.util.Properties;
import syncsim.Signal;
import syncsim.SoftPart;
public class AndPart extends SoftPart { protected final String PROP_BITWIDTH = "bitwidth"; // name of the property in the XML-file protected int bitWidth; // Storing the bitWidth-property of the AND-gate public AndPart() { } ...
The class definition is ready and we know how the part is supposed to work. Now we can start to define the inputs and outputs of the part. This is done by inheriting the two methods in() and out() from SoftPart. The methods doesn't take any arguments but they return a String which contains the ports and the ports bit widths separated by commas in the following format: name:width, name:width, ...
...

	public String in() {
		return "A:" + bitWidth + ", B:" + bitWidth;
	}

	public String out() {
		return "out:"+bitWidth;
	}

...

As shown in the code above, bitWidth is used when defining the in- and out-ports of the part. When bitWidth chages, the port declaration also changes. The next step is to implement the initialize method where the value for bitWidth will be read from the XML-file.

...

	public void initialize(String instanceName, Properties properties) {
		this.instanceName = instanceName;	

		// read the PROP_BITWIDTH property and then remove it from the Properties object
	   	String value = properties.getProperty( PROP_BITWIDTH );
		properties.remove( PROP_BITWIDTH );

		// the PROP_BITWIDTH property must be defined for this part to work, if it isn't throw an exception
		if (value == null) {
			throwMissingProperty( PROP_BITWIDTH );
		}

		// try to parse the value return from the Properties object into an integer
		try {
			bitWidth = Integer.parseInt(value);
		} catch (NumberFormatException e) {
			throwGeneralException( "Property '" + PROP_BITWIDTH + "' is not a number." );
		}

		// ensure that all properties defined in the XML-file was used
		if (properties.size() > 0) {
			throwUnknownProperties();		
		}
	}

...

This style of the initialize method should be followed to make the debugging of parts and designs easier. A misspelled 'bitwidth' in the XML-file won't be detected by the Loader. To avoid such errors you must check that all properties that were sent to the initialize method were consumed. The methods throwMissingProperty, throwUnknownProperties and throwGeneralException are defined in Part. All they do is to throw well formatted RuntimeExceptions.

Now it's time to implement the actual logic of the AND-gate. For combinatorial parts this is done in update whereas for synchronous parts it's done in step (not the whole truth). The update method takes two arrays as argument. The arrays are containing all signals on the ports of the part and the method is supposed to do all logic in this method.
...

	public void update(Signal[] in, Signal[] out) {	

		// only preform the logic if the insignals are valid

		if ( in[0].isValid() && in[1].isValid() ) {
			out[0] = new Signal(bitWidth, in[0].and(in[1]));
		}
	}
}
That's it, now we have a working AND-gate for the SoftSim simulator. The method isn't very hard to understand. First the in signals are checked so that they are valid. Then the AND-operation is performed by calling the and method from Signals superclass BigInteger and uses that result to create a new Signal. The Signals in SoftSim is constant and can't be changed, the only way to change the value of a port is to create a new Signal.

The source for AndPart.java or view it here
 
1.2 The graphical representation of a Part
In the previous section we learned how to create a combinatorial part for the SoftSim simulator. That's one step in the right direction but we also need some way to represent the gate in the simulator GUI. The answer is to search for already finished graphical representations and use one of them, or you can make you own by inheriting SSComponent. To make a simple graphical component you only have to implement the paint method. But if you want to have other tooltips or some sort of communication between your simulator part and your graphical component you'll have to implement more methods.
import java.awt.*;
import syncsim.SSComponent;


public class AndComponent extends SSComponent {
  
	public AndComponent() {
	}
  
	public void paint(Graphics g) {
		g.setColor(Color.black);
		g.drawRect(0, 0, getWidth()-1, getHeight()-1);
	}
}
This component only draws a rectangle that’s the size of the component. It’s preferable to make the graphics scalable because components can re resized in the XML-file.

The source for AndComponent.java or view it here
 
1.3 The Making of a register
Registers are synchronous and must therefore be derived from SoftSyncPart. The making of a register is basically the same as making an AND-gate, only a few things are different. We first make our class declaration then declare ports and finally the value for bitWidth is fetched.
import java.util.Properties;
import syncsim.SoftSyncPart;
import syncsim.Signal;
public class RegisterPart extends SoftSyncPart {
private static final String PROP_BITWIDTH = "bitwidth"; private int bitWidth; private Signal prevSignal; // representing the registers "memory" public RegisterPart() { } public String in() { return "in:" + bitWidth; } public String out() { return "out:" + bitWidth; } public void initialize(String instanceName, Properties properties) { super.initialize(instanceName, properties); String s = properties.getProperty(PROP_BITWIDTH); properties.remove(PROP_BITWIDTH); if (s == null) { throwMissingProperty(PROP_BITWIDTH); } try { bitWidth = Integer.parseInt(s); } catch (NumberFormatException e) { throwGeneralException("Property '" + PROP_BITWIDTH + "' is not a number."); } if (properties.size() > 0) { throwUnknownProperties(); } } ...
Nothing new there except that the Part is inheriting SoftSyncPart instead of SoftPart. In synchronous parts, both the update and the step method must be implemented. Step is the method that should calculate the output signals, while update only is used for refreshing the outputs.
	public void getOutput(Signal[] out) {
		out[0] = prevSignal;
	}
public void step(Signal[] in, Signal[] out) { prevSignal = in[0]; getOutput(out); }
public void update(Signal[] in, Signal[] out) { getOutput(out); } }
Each time step is called, the register saves the input signal and redirects it to the out port. When update is called the same signal is once again set at the out port. This saves a lot of calculations since update is called much more than step.

The source for RegisterPart.java or view it here
2.0 Making a design file
Designs are stored in an XML-file that can be loaded from the GUI. The file defines which parts that are going to be used, which graphical representation they will have and how they are connected.
<?xml version='1.0' encoding='UTF-8' ?>
<design>
<simulator class="syncsim.SoftSim"> <property Register:in="Register:out" />
</simulator> <component name="Register" class="syncsim.RegisterPart">
<gfx class="syncsim.MemoryComponent" width="40" height="25" x="100" y="100"> </gfx>
<property bitwidth="32" />
</component> </design>
The code above is a 32 bit register with its output connected to its input. This sort of connection isn't very meaningfull it is only an example of how the syntax looks. The first tag in the XML-file is the design tag where the whole design should be defined.
 
2.1 The Simulator tag
The simulator tag specifies which simulator is used when running the design file. Properties can be defined within all tags. These properties are sent to the initialize method of the class instance that the tag represent. In example above SoftSim gets the strange property Register:in="Register:out". In SoftSim this means that the port named 'in' of the part 'Register' will be connected to the port 'out' on the part 'Register'.

2.2 The Component tag
Simulator components are defined with a component tag. The class that is loaded in the component tag isn't anything that will show up in the GUI, it is only used by the simulator. If you want a graphical representation of the part you will need to declare one or more gfx tags. For example a wire is not always a straight line, it might go around a part to make it easier to follow. To avoid declaring several simulator components with one graphical component each, you can declare one simulator component and many graphical components.




SyncSim 2004